package com.dz.aspect;

import com.dz.annotation.AutoFill;
import com.dz.constant.AutoFillConstant;
import com.dz.context.BaseContext;
import com.dz.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @author 鄧浩奇
 * @classname AutoFillAspect
 * @description 自定义切面类,实现公共字段填充的逻辑
 * @since 2023/12/18 21:36
 **/


@Aspect     // 标识为一个切面
@Component  // 也是一个bean，需要交给Spring管理
@Slf4j      // 日志
public class AutoFillAspect {

    /*
    * 切入点，对哪些类的哪些方法进行拦截
    * */
    @Pointcut("execution(* com.dz.mapper.*.*(..)) && @annotation(com.dz.annotation.AutoFill)")  // 拦截规则：mapper包下的所有方法 并且 方法上面加了com.sky.annotation.AutoFill注解
    public void autoFillPointcut() {}

    /*
    * 配置前置通知，在方法执行前位公共字段赋值
    * */
    @Before("autoFillPointcut()")
    public void autoFill(JoinPoint joinPoint) {
        log.info("开始公共字段的填充.....");

        // 获取mapper方法类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);  // 获取方法上的注解对象
        OperationType operationType = annotation.value(); // 获取操作类型（insert还update）

        // 获取方法参数(默认实体类参数放在第一个位置)
        Object[] args = joinPoint.getArgs();
        if (Objects.isNull(args)) return;

        Object entity = args[0];
        // 准备填充的数据
        LocalDateTime now = LocalDateTime.now();
        Long id = BaseContext.getCurrentId();
        // 利用反射设置值
        if (operationType.equals(OperationType.INSERT)) {
            try {
                Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);

                // 通过反射为对象赋值
                setCreateTime.invoke(entity,now);
                setCreateUser.invoke(entity,id);
                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,id);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if (operationType.equals(OperationType.UPDATE)) {
            try {
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME,LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER,Long.class);

                setUpdateTime.invoke(entity,now);
                setUpdateUser.invoke(entity,id);
            } catch (Exception e) {
                e.printStackTrace();
            }
            
        }

    }
}
